package controllers

import (
	"baokaobang/datasourse"
	"baokaobang/logic"
	"baokaobang/models"
	"baokaobang/utils"
	"fmt"
	"math/rand"
	"strings"
	"time"

	"github.com/kataras/iris/v12"
	"github.com/kataras/iris/v12/sessions"
)

type User struct {
	Ctx iris.Context
}

type ListItem struct {
	Id           int64  `json:"id"`
	UniversityId int64  `json:"universityId"`
	MType        int    `json:"type"`
	Name         string `json:"name"`
	Avatar       string `json:"avatar"`
	NewMsg       string `json:"newMsg"`
	Time         string `json:"time"`
}

// 获取学生信息
func (c *User) PostStudentinfo() interface{} {
	channel := c.Ctx.PostValueDefault("channel", "")
	studentId := c.Ctx.PostValueDefault("studentId", "")

	if len(channel) <= 0 {
		return utils.CommonRes(1000, "请提供渠道", "")
	}
	if len(studentId) <= 0 {
		return utils.CommonRes(1000, "请提供学生id", "")
	}

	db, err := datasourse.NewMasterOrm()
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("无法连接数据库：%s", err.Error()), "")
	}

	student := new(models.UserStudentObj)
	_, err = db.Table(new(models.User)).Alias("u").
		Join("LEFT", []string{"high_school", "hs"}, "u.high_school_id = hs.id").
		Join("LEFT", []string{"high_school_class", "hsc"}, "u.high_school_class_id = hsc.id").
		Join("LEFT", []string{"region", "r"}, "hs.city_id = r.id").
		Where("u.id = ?", studentId).Get(student)
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("获取学生信息出错：%s", err.Error()), "")
	}

	student.UserData.SubjectShow = models.RankSubject[student.UserData.Subject]

	return utils.CommonRes(20000, "成功获取学生信息", student)
}

// 招办老师修改自己的信息
func (c *User) PostModify() interface{} {
	channel := c.Ctx.PostValueDefault("channel", "")
	mType := utils.Atoi(c.Ctx.PostValueDefault("type", "0"))
	content := c.Ctx.PostValueDefault("content", "")
	pictures := c.Ctx.PostValues("pictures")

	if len(channel) <= 0 {
		return utils.CommonRes(1000, "请提供渠道", "")
	}
	if mType <= 0 {
		return utils.CommonRes(1000, "请提供修改类型", "")
	}
	if mType == 3 {
		if len(pictures) <= 0 {
			return utils.CommonRes(1000, "请至少上传一张图片", "")
		}
	} else {
		if len(content) <= 0 {
			return utils.CommonRes(1000, "请输入修改内容", "")
		}
	}

	var userId int64
	if strings.EqualFold(channel, "wechat") {
		token := c.Ctx.GetHeader("token")
		claims, err := utils.ParseToken(token)
		if err != nil {
			return utils.CommonRes(1000, fmt.Sprintf("解析token出错：%s", err.Error()), "")
		}
		userId = utils.Atoi64(claims.Id)
	} else {
		session := sessions.Get(c.Ctx)
		userId, _ = session.GetInt64(fmt.Sprintf("%sUserId", channel))
	}

	var updateData map[string]interface{}
	if mType == 1 {
		updateData = map[string]interface{}{
			"area": content,
		}
	} else if mType == 2 {
		updateData = map[string]interface{}{
			"greet": content,
		}
	} else if mType == 3 {
		updateData = map[string]interface{}{
			"album_list": strings.Join(pictures, ","),
		}
	}

	db, err := datasourse.NewMasterOrm()
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("无法连接数据库：%s", err.Error()), "")
	}

	_, err = db.Table(new(models.User)).ID(userId).Update(updateData)
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("操作失败：%s", err.Error()), "")
	}

	return utils.CommonRes(20000, "操作成功", "")
}

// 获取招办老师信息
func (c *User) PostInfo() interface{} {
	uid := c.Ctx.PostValueDefault("uid", "0")

	db, err := datasourse.NewMasterOrm()
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("无法连接数据库：%s", err.Error()), "")
	}

	user := new(models.UserData)
	_, err = db.Table(new(models.User)).ID(uid).Get(user)
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("获取用户信息失败：%s", err.Error()), "")
	}

	user.PhoneShow = utils.FormatMobile(user.Phone)
	user.Albums = strings.Split(user.AlbumList, ",")

	college := new(models.College)
	if user.UserType == 2 || user.UserType == 3 {
		ok, err := db.ID(user.CollegeId).Get(college)
		if err != nil {
			return utils.CommonRes(1000, fmt.Sprintf("根据学院id查询出错：%s", err.Error()), "")
		}
		if !ok {
			return utils.CommonRes(1000, "用户学院信息不存在", "")
		}
		user.CollegeName = college.Name
	}

	return utils.CommonRes(20000, "获取用户信息成功", user)
}

// 学生修改高考成绩
func (c *User) PostScore() interface{} {
	channel := c.Ctx.PostValueDefault("channel", "")
	score := utils.Atoi(c.Ctx.PostValueDefault("score", "0"))

	if len(channel) <= 0 {
		return utils.CommonRes(1000, "请提供渠道", "")
	}
	if score < 100 {
		return utils.CommonRes(1000, "您输入的成绩过低，无法匹配到院校", "")
	}

	var userId int64
	if strings.EqualFold(channel, "wechat") {
		token := c.Ctx.GetHeader("token")
		claims, err := utils.ParseToken(token)
		if err != nil {
			return utils.CommonRes(1000, fmt.Sprintf("解析token出错：%s", err.Error()), "")
		}
		userId = utils.Atoi64(claims.Id)
	} else {
		session := sessions.Get(c.Ctx)
		userId, _ = session.GetInt64(fmt.Sprintf("%sUserId", channel))
	}

	db, err := datasourse.NewMasterOrm()
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("无法连接数据库：%s", err.Error()), "")
	}

	sess := db.NewSession()
	defer sess.Close()
	err = sess.Begin()
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("数据库事务开启失败：%s", err.Error()), "")
	}

	// 根据学生成绩更新学生信息，并为学生匹配院校
	return logic.MatchCollege(sess, userId, score)
}

// 招办专家一对一
func (c *User) PostOnetoone() interface{} {
	channel := c.Ctx.PostValueDefault("channel", "")

	if len(channel) <= 0 {
		return utils.CommonRes(1000, "请提供渠道", "")
	}

	var userId int64
	if strings.EqualFold(channel, "wechat") {
		token := c.Ctx.GetHeader("token")
		claims, err := utils.ParseToken(token)
		if err != nil {
			return utils.CommonRes(1000, fmt.Sprintf("解析token出错：%s", err.Error()), "")
		}
		userId = utils.Atoi64(claims.Id)
	} else {
		session := sessions.Get(c.Ctx)
		userId, _ = session.GetInt64(fmt.Sprintf("%sUserId", channel))
	}

	db, err := datasourse.NewMasterOrm()
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("无法连接数据库：%s", err.Error()), "")
	}

	ok, err := db.Table(new(models.MatchTeacher)).Where("student_id = ? and match_type = 3", userId).Exist()
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("匹配招办专家出错：%s", err.Error()), "")
	}
	if ok {
		return utils.CommonRes(1000, "您已匹配过专家一对一了", "")
	}

	teacherList := make([]models.User, 0)
	err = db.Table(new(models.User)).Where("user_type = 3").Find(&teacherList)
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("查询所有专家出错：%s", err.Error()), "")
	}
	if len(teacherList) <= 0 {
		return utils.CommonRes(1000, "没有匹配到任何专家", "")
	}

	rand.Seed(time.Now().UnixNano())
	teacherLen := len(teacherList) - 1
	matchTeacher := new(models.MatchTeacher)
	matchTeacher.MatchType = 3
	matchTeacher.StudentId = userId
	matchTeacher.TeacherId = teacherList[rand.Intn(teacherLen)].Id
	_, err = db.InsertOne(matchTeacher)
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("专家匹配出错：%s", err.Error()), "")
	}

	return utils.CommonRes(20000, "操作成功", "")
}

// 获取当前登录用户的群聊列表
func (c *User) PostChatgroup() interface{} {
	channel := c.Ctx.PostValueDefault("channel", "")

	if len(channel) <= 0 {
		return utils.CommonRes(1000, "请提供渠道", "")
	}

	var userId int64
	if strings.EqualFold(channel, "wechat") {
		token := c.Ctx.GetHeader("token")
		claims, err := utils.ParseToken(token)
		if err != nil {
			return utils.CommonRes(1000, fmt.Sprintf("解析token出错：%s", err.Error()), "")
		}
		userId = utils.Atoi64(claims.Id)
	} else {
		session := sessions.Get(c.Ctx)
		userId, _ = session.GetInt64(fmt.Sprintf("%sUserId", channel))
	}

	db, err := datasourse.NewMasterOrm()
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("无法连接数据库：%s", err.Error()), "")
	}

	user := new(models.User)
	_, err = db.ID(userId).Get(user)
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("查询用户信息出错：%s", err.Error()), "")
	}

	siteConfig := new(models.SiteConfig)
	_, err = db.ID(1).Get(siteConfig)
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("查询网站配置信息出错：%s", err.Error()), "")
	}

	year := time.Now().Format("2006")
	list := make([]ListItem, 0)

	if user.UserType == 1 {
		matchTeacherList := make([]models.MatchTeacherData, 0)
		err = db.Table(new(models.MatchTeacher)).Alias("mt").
			Join("INNER", []string{"user", "u"}, "mt.teacher_id = u.id").
			Where("mt.student_id = ?", user.Id).Find(&matchTeacherList)
		if err != nil {
			return utils.CommonRes(1000, fmt.Sprintf("查询群聊列表出错：%s", err.Error()), "")
		}
		for _, matchTeacher := range matchTeacherList {
			name := ""
			if matchTeacher.UserData.UserType == 2 {
				college := new(models.CollegeData)
				_, err = db.ID(matchTeacher.UserData.CollegeId).Get(college)
				if err != nil {
					return utils.CommonRes(1000, fmt.Sprintf("查询群聊列表出错：%s", err.Error()), "")
				}
				name = fmt.Sprintf("%s(%s)", college.Name, matchTeacher.UserData.ShortName)
			} else if matchTeacher.UserData.UserType == 3 {
				name = fmt.Sprintf("一对一专家(%s)", matchTeacher.UserData.ShortName)
			} else if matchTeacher.UserData.UserType == 4 {
				name = fmt.Sprintf("辅导员(%s)", matchTeacher.UserData.ShortName)
			}
			listItem := ListItem{
				Id:     matchTeacher.MatchTeacher.Id,
				MType:  2,
				Name:   name,
				Avatar: matchTeacher.UserData.Avatar,
				NewMsg: "",
				Time:   "",
			}
			list = append(list, listItem)
		}

		score := 0
		if siteConfig.IsTest == 1 {
			score = user.TestScore
		} else {
			score = user.SimulateScore
		}

		mType := 1
		if user.IsBuySingleAction == 1 {
			mType = 2
		}

		matchCollegeList := make([]models.MatchCollegeData, 0)
		err = db.Table(new(models.MatchCollege)).Alias("mc").
			Join("INNER", []string{"college", "c"}, "mc.college_id = c.id").
			Join("INNER", []string{"university", "u"}, "c.university_id = u.id").
			Where("mc.user_id = ? and mc.year = ? and mc.score = ? and mc.match_type = ? and mc.is_test = ? and mc.is_buy_ensure_admission = ?", user.Id, year, score, mType, siteConfig.IsTest, user.IsBuyEnsureAdmission).
			Find(&matchCollegeList)
		if err != nil {
			return utils.CommonRes(1000, fmt.Sprintf("查询群聊列表出错：%s", err.Error()), "")
		}

		for _, matchCollege := range matchCollegeList {
			name := fmt.Sprintf("%s招办咨询群", matchCollege.CollegeData.Name)
			listItem := ListItem{
				Id:           matchCollege.CollegeData.Id,
				UniversityId: matchCollege.UniversityData.Id,
				MType:        3,
				Name:         name,
				Avatar:       matchCollege.UniversityData.LogoPic,
				NewMsg:       "",
				Time:         "",
			}
			list = append(list, listItem)
		}
	} else if user.UserType == 2 { // 招办老师
		college := new(models.CollegeObj)
		_, err = db.Table(new(models.College)).Alias("c").
			Join("INNER", []string{"university", "u"}, "c.university_id = u.id").
			Where("c.id = ?", user.CollegeId).Get(college)
		if err != nil {
			return utils.CommonRes(1000, fmt.Sprintf("查询群聊列表出错：%s", err.Error()), "")
		}
		name := fmt.Sprintf("%s招办咨询群", college.CollegeData.Name)
		listItem := ListItem{
			Id:           college.CollegeData.Id,
			UniversityId: college.UniversityData.Id,
			MType:        3,
			Name:         name,
			Avatar:       college.UniversityData.LogoPic,
			NewMsg:       "",
			Time:         "",
		}
		list = append(list, listItem)
	} else if user.UserType == 3 || user.UserType == 4 { // 招办专家和辅导员
		matchStudentList := make([]models.MatchTeacherData, 0)
		err = db.Table(new(models.MatchTeacher)).Alias("mt").
			Join("INNER", []string{"user", "u"}, "mt.student_id = u.id").
			Where("mt.teacher_id = ?", user.Id).Find(&matchStudentList)
		if err != nil {
			return utils.CommonRes(1000, fmt.Sprintf("查询群聊列表出错：%s", err.Error()), "")
		}
		for _, matchStudent := range matchStudentList {
			listItem := ListItem{
				Id:     matchStudent.UserData.Id,
				MType:  2,
				Name:   matchStudent.UserData.ShortName,
				Avatar: matchStudent.UserData.Avatar,
				NewMsg: "",
				Time:   "",
			}
			list = append(list, listItem)
		}
	}

	return utils.CommonRes(20000, "成功获取群聊列表", list)
}

// 填写邀请码
func (c *User) PostInvitecode() interface{} {
	channel := c.Ctx.PostValueDefault("channel", "")
	inviteCode := strings.TrimSpace(c.Ctx.PostValueDefault("inviteCode", ""))

	if len(channel) <= 0 {
		return utils.CommonRes(1000, "请提供渠道", "")
	}
	if len(inviteCode) <= 0 {
		return utils.CommonRes(1000, "请输入邀请码", "")
	}

	db, err := datasourse.NewMasterOrm()
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("无法连接数据库：%s", err.Error()), "")
	}

	sess := db.NewSession()
	defer sess.Close()
	err = sess.Begin()
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("数据库事务开启失败：%s", err.Error()), "")
	}

	var userId int64
	if strings.EqualFold(channel, "wechat") {
		token := c.Ctx.GetHeader("token")
		claims, err := utils.ParseToken(token)
		if err != nil {
			return utils.CommonRes(1000, fmt.Sprintf("解析token出错：%s", err.Error()), "")
		}
		userId = utils.Atoi64(claims.Id)
	} else {
		session := sessions.Get(c.Ctx)
		userId, _ = session.GetInt64(fmt.Sprintf("%sUserId", channel))
	}

	user := new(models.User)
	_, err = sess.ID(userId).Get(user)
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("查询用户出错：%s", err.Error()), "")
	}
	if user.ParentId > 0 {
		return utils.CommonRes(1000, "您已经填写过邀请码了", "")
	}

	inviteUser := new(models.User)
	ok, err := sess.Where("`invite_code` = ?", inviteCode).Get(inviteUser)
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("根据邀请码查询用户失败：%s", err.Error()), "")
	}
	if !ok {
		return utils.CommonRes(1000, "邀请码不存在", "")
	}

	invite := new(models.Invite)
	invite.ShareUserId = inviteUser.Id
	invite.RegUserId = user.Id
	invite.Code = inviteCode
	_, err = sess.InsertOne(invite)
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("邀请码添加失败：%s", err.Error()), "")
	}

	updateData := map[string]interface{}{
		"parent_id": inviteUser.Id,
	}
	_, err = sess.Table(new(models.User)).ID(user.Id).Update(updateData)
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("用户信息更新失败：%s", err.Error()), "")
	}

	sess.Commit()

	return utils.CommonRes(20000, "操作成功", "")
}

// 用户登录修改密码
func (c *User) PostModifypassword() interface{} {
	channel := strings.TrimSpace(c.Ctx.PostValueDefault("channel", ""))
	password := strings.TrimSpace(c.Ctx.PostValueDefault("password", ""))
	newPassword := strings.TrimSpace(c.Ctx.PostValueDefault("newPassword", ""))
	confirmPassword := strings.TrimSpace(c.Ctx.PostValueDefault("confirmPassword", ""))

	if len(channel) <= 0 {
		return utils.CommonRes(1000, "请提供渠道", "")
	}
	if len(password) <= 0 {
		return utils.CommonRes(1000, "请输入旧密码", "")
	}
	if len(newPassword) <= 0 {
		return utils.CommonRes(1000, "请输入新密码", "")
	}
	if len(confirmPassword) <= 0 {
		return utils.CommonRes(1000, "请再次输入新密码", "")
	}
	if !strings.EqualFold(newPassword, confirmPassword) {
		return utils.CommonRes(1000, "两次新密码输入不一致", "")
	}

	var userId int64
	if strings.EqualFold(channel, "wechat") {
		token := c.Ctx.GetHeader("token")
		claims, err := utils.ParseToken(token)
		if err != nil {
			return utils.CommonRes(1000, fmt.Sprintf("解析token出错：%s", err.Error()), "")
		}
		userId = utils.Atoi64(claims.Id)
	} else {
		session := sessions.Get(c.Ctx)
		userId, _ = session.GetInt64(fmt.Sprintf("%sUserId", channel))
	}

	db, err := datasourse.NewMasterOrm()
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("无法连接数据库:%s", err.Error()), "")
	}

	user := new(models.User)
	db.ID(userId).Get(user)
	if !strings.EqualFold(user.Password, utils.PasswordEncode(password)) {
		return utils.CommonRes(1000, "旧密码不正确", "")
	}

	updateData := map[string]interface{}{
		"password": utils.PasswordEncode(newPassword),
	}
	_, err = db.Table(new(models.User)).ID(userId).Update(updateData)
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("修改密码失败：%s", err.Error()), "")
	}

	return utils.CommonRes(20000, "密码修改成功", "")
}

// 退出登录
func (c *User) PostLogout() interface{} {
	channel := c.Ctx.PostValueDefault("channel", "mini")

	if len(channel) <= 0 {
		return utils.CommonRes(1000, "请提供渠道", "")
	}

	session := sessions.Get(c.Ctx)
	session.Delete(fmt.Sprintf("%sUserId", channel))

	return utils.CommonRes(20000, "成功退出登录", "")
}
